#include "NodeVisitor.h"
#include <iostream>
using namespace std;

void CompressionVisitor::visit(CompilationUnitNode *n) { 
	n->FlattenOn("TypeDeclaration");
	n->FlattenOn("ImportDeclarations");
	n->FlattenOn("ImportDeclaration");
}
void CompressionVisitor::visit(ClassDeclarationNode *n) {
	n->FlattenOn("Super");
	n->FlattenOn("Interfaces");
	n->FlattenOn("InterfaceTypeList");
	n->FlattenOn("ClassBody");
	n->DeleteLeafs();
	n->FlattenOn("ClassBodyDeclarations");
	n->FlattenOn("ClassBodyDeclaration");
	n->FlattenOn("ClassMemberDeclaration");
}

void CompressionVisitor::visit(ModifiersNode *n) {
	n->FlattenOn("Modifiers");
	n->FlattenOn("Modifier");
}

void CompressionVisitor::visit(VariableDeclaratorNode *n) {
	ParentNode *parent = n->parent;

	n->FlattenOn("VariableInitializer");
	parent->FlattenOn("VariableDeclarator");
	parent->DeleteLeafs();
	current_is_gone = true;
}

void CompressionVisitor::visit(MethodHeaderNode *n) {
	ParentNode *parent = n->parent;

	parent->FlattenOn("MethodBody");
	n->FlattenOn("MethodDeclarator");
	parent->FlattenOn("MethodHeader");
	current_is_gone = true;
}
void CompressionVisitor::visit(FormalParameterListNode *n) {
	n->FlattenOn("FormalParameterList");
	n->parent->FlattenOn("FormalParameterList");
	current_is_gone = true;
}
void CompressionVisitor::visit(ConstructorDeclarationNode *n) {
	n->FlattenOn("ConstructorDeclarator");
	n->FlattenOn("ConstructorBody");
}

void CompressionVisitor::visit(InterfaceDeclarationNode *n) {
	n->FlattenOn("ExtendsInterfaces");
	n->FlattenOn("InterfaceBody");
	n->DeleteLeafs();
	n->FlattenOn("InterfaceMemberDeclarations");
	n->FlattenOn("InterfaceMemberDeclaration");
}

void CompressionVisitor::visit(BlockNode *n) {
	n->FlattenOn("BlockStatements");
	n->FlattenOn("BlockStatement");
	n->FlattenOn("LocalVariableDeclarationStatement");
	n->DeleteLeafs();
}
void CompressionVisitor::visit(BlockStatementNode *n) {
}
void CompressionVisitor::visit(LocalVariableDeclarationNode *n) {
	n->FlattenOn("VariableInitializer");
}

void CompressionVisitor::visit(ClassInstanceCreationExpressionNode *n) {
	n->FlattenOn("ClassType");
	n->DeleteLeafs();
}
void CompressionVisitor::visit(ArgumentListNode *n) {
	n->FlattenOn("ArgumentList");
	n->DeleteLeafs();
	n->parent->FlattenOn("ArgumentList");
	current_is_gone = true;
}
void CompressionVisitor::visit(ArrayCreationExpressionNode *n) {
	n->children[1] = TypeNode().Convert((ParentNode*)n->children[1]());
	n->children[1]()->parent = n;
}
void CompressionVisitor::visit(CastExpressionNode *n) {
	ExpressionNode *expr = (ExpressionNode*)(*n)["Expression"];
	if (expr) {
		string child_type = string();
		while (expr->children.size() == 1) {
			child_type = expr->children[0]()->Type();
			if (child_type == "PostfixExpression" || ((ParentNode*)expr->children[0]())->children.size() > 1) break;
			expr->FlattenOn(child_type);
		}

		expr->FlattenOn("PostfixExpression");
		if (expr->children.size() == 1 && expr->children[0]()->Type() == "Name") n->FlattenOn("Expression");
	} 

	if (!(*n)["Expression"]){
		SP<ParseNode> c = n->children[1];
		TypeNode *tn = new TypeNode();

		if ((*n)["PrimitiveArrayType"] || (*n)["ObjectArrayType"]) {
			ArrayTypeNode *atn = new ArrayTypeNode();
			atn->children.push_back(c);
			c = atn;
		}

		tn->children.push_back(c);
		tn->parent = n;
		n->children[1] = tn;
	}

}
void CompressionVisitor::visit(TypeNode *n) {
	//Flatten references
	n->FlattenOn("ReferenceType");
	n->isArray = (n->children[0]()->Type() == "ArrayType");

	n->FlattenOn("Type");
	n->FlattenOn("ArrayType");
	n->FlattenOn("PrimitiveArrayType");
	n->FlattenOn("ObjectArrayType");

	//Flatten primitives
	n->FlattenOn("PrimitiveType");
	n->FlattenOn("NumericType");
	n->FlattenOn("IntegralType");

}
void CompressionVisitor::visit(ReferenceTypeNode *n) {
	n->children.push_back(new TypeNode());
	((ParentNode*)n->children[1]())->children.push_back(n->children[0]);
	n->children.erase(n->children.begin());
	n->children[0]()->parent = n;
}
void CompressionVisitor::visit(QualifiedNameNode *n) {
	ParentNode *p = n->parent;
	p->FlattenOn("QualifiedName");
	p->FlattenOn("Name");
	p->FlattenOn(".");

	current_is_gone = true;
}
void CompressionVisitor::visit(SimpleNameNode *n) {
	n->ReplaceMeWith(n->children[0]());
	current_is_gone = true;
}
void CompressionVisitor::visit(LiteralNode *n) {
	//while (n->parent->Type() != "Expression" && n->parent->children.size() == 1) n->parent->ReplaceMeWith(n);
}
void CompressionVisitor::visit(StatementNode *n){
	if (n->children[0]()->Type() == "Statement"){
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(IfStatementNode *n){
	ParentNode *last_child = (ParentNode*)n->children.back()();
	
	bool has_else = n->HasChildOfType("else");
	bool has_else_if = has_else && last_child->children[0]()->Type() == "IfStatement";
	
	n->DeleteLeafs();
	while(has_else_if) {
		last_child->ReplaceMeWith(last_child->children[0]());
		n->FlattenOn("IfStatement");

		last_child = (ParentNode*)n->children.back()();
		has_else = n->HasChildOfType("else");
		has_else_if = has_else && last_child->children[0]()->Type() == "IfStatement";
		n->DeleteLeafs();
	};

	if (!has_else) return;

	ParentNode *itesn = IfThenElseStatementNode().Convert(n);
	n->ReplaceMeWith(itesn);
	for (vector<SP<ParseNode> >::iterator it = itesn->children.begin(); it < itesn->children.end(); ++it) (*it)()->parent = itesn;
}
void CompressionVisitor::visit(ForStatementNode *n) {
	//Wrap for statements in a block to give proper environments
	if (n->parent->Type() != "Block") {
		BlockNode *bn = new BlockNode();
		bn->children.push_back(n);
		n->ReplaceMeWith(bn);
		n->parent = bn;
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(ConditionalOrExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(ConditionalAndExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(InclusiveOrExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(ExclusiveOrExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(AndExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(EqualityExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(RelationalExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(AdditiveExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(MultiplicativeExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(UnaryExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(UnaryExpressionNotPlusMinusNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(PostfixExpressionNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(PrimaryNode *n) {
	if (n->children.size() == 1) {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
}
void CompressionVisitor::visit(PrimaryNoNewArrayNode *n) {
	if (n->children[0]()->Type() == "Literal") {
		n->ReplaceMeWith(n->children[0]());
		current_is_gone = true;
	}
	n->DeleteLeafs();
}
